﻿/*
 * This class provides the methods to interact with the configuration database created in sql compact edition.
 * <para>Entity model framework is used to generate the database entities.
 * <para>The database structure can be seen by opening the Configuration.edmx file in this project.
 */

using System;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Collections.Generic;
using Valentia.Kinection.DataTypes;
using Valentia.Kinection.Configuration;

namespace Valentia.Kinection.Configuration
{
    /// <summary>
    /// Configuration helper class.
    /// <para>This class provides the methods to interact with the configuration database created in sql compact edition.</para>
    /// <para>Entity model framework is used to generate the database entities.</para>
    /// <para>The database structure can be seen by opening the Configuration.edmx file in this project.</para>
    /// </summary>
    public static class ConfigurationHelper
    {
        #region DATA MEMBERS
        /// <summary>
        ///  Objects that already exist in the object context are not loaded from the data source.
        /// </summary>
        private static MergeOption executeMergeOption = MergeOption.AppendOnly;

        /// <summary>
        /// Database connection string.
        /// </summary>
        private static String connectionString =
            @"metadata=res://*/Configuration.csdl|res://*/Configuration.ssdl|res://*/Configuration.msl;provider=System.Data.SqlServerCe.3.5;" +
            @"provider connection string=""Data Source=|DataDirectory|\ConfigDatabase.sdf"";";
        #endregion

        #region STATIC CONSTRUCTOR
        /// <summary>
        /// Static constructor.
        /// </summary>
        static ConfigurationHelper()
        {
            #region Saving values of notification IDs in Notification table if not already exists.

            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {

                ObjectQuery<Notification> query =
                    context.CreateQuery<Notification>(
                    "Select value n from Notifications as n Where n.NotificationID = @NotificationID", new ObjectParameter("NotificationID", typeof(int)));

                foreach (String notificationType in Enum.GetNames(typeof(NotificationType)))
                {
                    int notificationTypeInt = (int)((NotificationType)(Enum.Parse(typeof(NotificationType), notificationType, true)));
                    query.Parameters["NotificationID"].Value = notificationTypeInt;

                    if (query.Execute(ConfigurationHelper.executeMergeOption).Count() > 0) continue;

                    Notification notif = new Notification();
                    notif.NotificationID = notificationTypeInt;
                    context.Notifications.AddObject(notif);
                }

                context.SaveChanges();
            }

            #endregion

            #region Saving values of skeleton joints IDs in SkeletonJoint table if not already exists.

            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<SkeletonJoint> query =
                    context.CreateQuery<SkeletonJoint>(
                    "Select value n from SkeletonJoints as n Where n.JointID = @JointID", new ObjectParameter("JointID", 1));

                foreach (String skeletonJoint in Enum.GetNames(typeof(SkeletonJointID)))
                {
                    int skeletonJointInt
                        = (int)((SkeletonJointID)(Enum.Parse(typeof(SkeletonJointID)
                        , skeletonJoint, true)));

                    query.Parameters["JointID"].Value = skeletonJointInt;

                    if (query.Execute(ConfigurationHelper.executeMergeOption).Count() > 0) continue;

                    SkeletonJoint skelJoint = new SkeletonJoint();
                    skelJoint.JointID = skeletonJointInt;
                    context.SkeletonJoints.AddObject(skelJoint);
                }

                context.SaveChanges();
            }

            #endregion
        }
        #endregion

        #region METHODS
        /// <summary>
        /// Used to get context for querying and working with entity objects.
        /// </summary>
        /// <returns>ConfigDatabaseEntities.</returns>
        public static ConfigDatabaseEntities GetContext()
        {
            return new ConfigDatabaseEntities(ConfigurationHelper.connectionString);
        }

        #region KINECT DEVICE RELATED METHODS
        /// <summary>
        /// Gets all the registered kinect devices.
        /// </summary>
        /// <returns>list of kinect devices.</returns>
        public static List<KinectDevice> GetAllKinectDevices()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<KinectDevice> query = context.CreateQuery<KinectDevice>("Select value p from KinectDevices as p");
                ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Gets the kinect device by the name.
        /// </summary>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>Kinect device if found else will return null.</returns>
        public static KinectDevice GetKinectDeviceByName(String kinectDeviceName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetKinectDeviceByName(context, kinectDeviceName);
            }
        }

        /// <summary>
        /// Gets the kinect device by the name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>Kinect device if found else will return null.</returns>
        public static KinectDevice GetKinectDeviceByName(ConfigDatabaseEntities context, String kinectDeviceName)
        {
            ObjectQuery<KinectDevice> query =
                    context.CreateQuery<KinectDevice>(
                    "Select value p from KinectDevices as p Where p.KinectDeviceName = @KinectDeviceName", new ObjectParameter("KinectDeviceName", kinectDeviceName));
            ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (KinectDevice kinectDevice in results) { return kinectDevice; }

            return null;
        }

        /// <summary>
        /// Saves the kinect device to application database.
        /// </summary>
        /// <param name="kinectDeviceID">Kinect device ID.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>Saved kinect device object.</returns>
        public static KinectDevice SaveKinectDevice(String kinectDeviceID, String kinectDeviceName)
        {
            //The kinect device is saved with the default values for smoothing parameters, resoloutions and image type. All the bits values for active,
            //Color image, depth image and skeleton image are enabled
            return ConfigurationHelper.SaveKinectDevice(
                kinectDeviceID, kinectDeviceName, true,
                (KinectRuntimeOptions.UseDepthAndPlayerIndex | KinectRuntimeOptions.UseSkeletalTracking | KinectRuntimeOptions.UseColor), true, true, true,
                1.0f, 0.1f, 0.1f, 0.05f, 0.05f, KinectImageResolution.Resolution640x480, KinectImageResolution.Resolution320x240,
                KinectImageResolution.Resolution640x480, KinectImageType.Color, KinectImageType.DepthAndPlayerIndex);
        }

        /// <summary>
        /// Saves the kinect device to application database.
        /// </summary>
        /// <param name="kinectDeviceID">Kinect device ID.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <param name="active">True if device to be active else false.</param>
        /// <param name="kinectRuntimeOptions">Run time initialization options.</param>
        /// <param name="generateVideoStream">True to generate video stream else false.</param>
        /// <param name="generateDepthStream">True to depth video stream else false.</param>
        /// <param name="generateSkeletonStream">True to skeleton video stream else false.</param>
        /// <param name="skeletonSmoothing">Skeleton Smoothing parameter.</param>
        /// <param name="skeletonCorrection">Skeleton Correction parameter.</param>
        /// <param name="skeletonPrediction">Skeleton Prediction parameter.</param>
        /// <param name="skeletonJitterRadius">Skeleton JitterRadius parameter.</param>
        /// <param name="skeletonMaxDeviationRadius">Skeleton smoothing parameter.</param>
        /// <param name="videoResoloution">Video resoloution.</param>
        /// <param name="depthResoloution">Depth resoloution.</param>
        /// <param name="skeletonResoloution">Skeleton resoloution.</param>
        /// <returns>Saved kinect device object.</returns>
        public static KinectDevice SaveKinectDevice(
            String kinectDeviceID, String kinectDeviceName, bool active, KinectRuntimeOptions kinectRuntimeOptions, bool generateVideoStream, bool generateDepthStream,
            bool generateSkeletonStream, double skeletonSmoothing, double skeletonCorrection, double skeletonPrediction, double skeletonJitterRadius,
            double skeletonMaxDeviationRadius, KinectImageResolution videoResoloution, KinectImageResolution depthResoloution,
            KinectImageResolution skeletonResoloution, KinectImageType kinectVideoImageType, KinectImageType kinectDepthImageType)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveKinectDevice(context, new KinectDevice()
                {
                    KinectDeviceID = kinectDeviceID,
                    KinectDeviceName = kinectDeviceName,
                    Active = active,
                    KinectRuntimeOptions = kinectRuntimeOptions,
                    GenerateVideoStream = generateVideoStream,
                    GenerateDepthStream = generateDepthStream,
                    GenerateSkeletonStream = generateSkeletonStream,
                    SkeletonSmoothing = skeletonSmoothing,
                    SkeletonCorrection = skeletonCorrection,
                    SkeletonPrediction = skeletonPrediction,
                    SkeletonJitterRadius = skeletonJitterRadius,
                    SkeletonMaxDeviationRadius = skeletonMaxDeviationRadius,
                    ID = context.KinectDevices.NextId(f => f.ID),
                    KinectVideoResoloution = videoResoloution,
                    KinectDepthResoloution = depthResoloution,
                    KinectSkeletonResoloution = skeletonResoloution,
                    KinectVideoImageType = kinectVideoImageType,
                    KinectDepthImageType = kinectDepthImageType,
                });
            }
        }

        /// <summary>
        /// Saves the kinect device to application database.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="kinectDevice">Kinect device to save.</param>
        /// <returns>Saved kinect device object.</returns>
        public static KinectDevice SaveKinectDevice(ConfigDatabaseEntities context, KinectDevice kinectDevice)
        {
            return context.KinectDevices.AddAndSaveChanges(context, kinectDevice);
        }

        /// <summary>
        /// Deletes kinect device from database using device name.
        /// </summary>
        /// <param name="kinectDeviceName">Device name to be used.</param>
        /// <returns>True if kinect device deleted successfuly else False.</returns>
        public static bool DeleteKinectDeviceByName(String kinectDeviceName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteKinectDeviceByName(context, kinectDeviceName))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Deletes kinect device from database using device name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="kinectDeviceName">Kinect device name.</param>
        /// <returns>True if kinect device deleted successfuly else False.</returns>
        public static bool DeleteKinectDeviceByName(ConfigDatabaseEntities context, String kinectDeviceName)
        {
            ObjectQuery<KinectDevice> query =
                    context.CreateQuery<KinectDevice>(
                    "Select value p from KinectDevices as p Where p.KinectDeviceName = @KinectDeviceName", new ObjectParameter("KinectDeviceName", kinectDeviceName));
            ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (KinectDevice kinectDevice in results)
            {
                context.KinectDevices.DeleteObject(kinectDevice);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Deletes all the registered kinect devices.
        /// </summary>
        /// <returns>True if all kinect devices deleted successfuly else False.</returns>
        public static bool DeleteAllKinectDevices()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<KinectDevice> query = context.CreateQuery<KinectDevice>("Select value p from KinectDevices as p");
                ObjectResult<KinectDevice> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (KinectDevice kinectDevice in results)
                {
                    context.KinectDevices.DeleteObject(kinectDevice);
                }

                context.SaveChanges();

                return true;
            }
        }
        #endregion

        #region DATA USER RELATED METHODS
        /// <summary>
        /// Gets all service clients.
        /// </summary>
        /// <returns>List of service clients.</returns>
        public static List<DataUser> GetAllDataUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<DataUser> query = context.CreateQuery<DataUser>("Select value p from DataUsers as p");
                ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Gets the service client by the login name.
        /// </summary>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>Service client if found else will return null.</returns>
        public static DataUser GetDataUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetDataUserByLoginName(context, loginName);
            }
        }

        /// <summary>
        /// Gets the service client by the login name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>Service client if found else will return null.</returns>
        public static DataUser GetDataUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<DataUser> query =
                    context.CreateQuery<DataUser>(
                    "Select value p from DataUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));
            ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (DataUser dataUser in results) { return dataUser; }

            return null;

        }

        /// <summary>
        /// Saves the service client to application database.
        /// </summary>
        /// <param name="name">Service client name.</param>
        /// <param name="login">Service client login name.</param>
        /// <param name="password">Service client password.</param>
        /// <returns>Saved service client object.</returns>
        public static DataUser SaveDataUser(String name, String login, String password)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUser(context, new DataUser()
                {
                    ID = context.DataUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = true,
                    SendVideoFrame = true,
                    SendDepthFrame = true,
                    SendSkeletonFrame = true,
                });
            }
        }

        /// <summary>
        /// Saves the service client to application database.
        /// </summary>
        /// <param name="name">Service client name.</param>
        /// <param name="login">Service client login name.</param>
        /// <param name="password">Service client password.</param>
        /// <param name="active">Service client is active.</param>
        /// <param name="sendVideoFrame">Service client can recieve video frame.</param>
        /// <param name="sendDepthFrame">Service client can recieve depth frame.</param>
        /// <param name="sendSkeletonFrame">Service client can recieve skeleton frame.</param>
        /// <returns>Saved service client object.</returns>
        public static DataUser SaveDataUser(String name, String login, String password, bool active, bool sendVideoFrame, bool sendDepthFrame, bool sendSkeletonFrame)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUser(context, new DataUser()
                {
                    ID = context.DataUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = active,
                    SendVideoFrame = sendVideoFrame,
                    SendDepthFrame = sendDepthFrame,
                    SendSkeletonFrame = sendSkeletonFrame,
                });
            }
        }

        /// <summary>
        /// Saves the service client to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUser">Saved service client object.</param>
        public static DataUser SaveDataUser(ConfigDatabaseEntities context, DataUser dataUser)
        {
            return context.DataUsers.AddAndSaveChanges(context, dataUser);
        }

        /// <summary>
        /// Delete service client by login name
        /// </summary>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>True if user deleted successfully else False.</returns>
        public static bool DeleteDataUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteDataUserByLoginName(context, loginName))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Delete service client by login name
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Service client login name.</param>
        /// <returns>True if user deleted successfully else False.</returns>
        public static bool DeleteDataUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<DataUser> query =
                    context.CreateQuery<DataUser>(
                    "Select value p from DataUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));
            ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (DataUser dataUser in results)
            {
                context.DataUsers.DeleteObject(dataUser);
                return true;
            }

            return false;

        }

        /// <summary>
        /// Delete all Service clients
        /// </summary>
        /// <returns>True if all users deleted successfully else False</returns>
        public static bool DeleteAllDataUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<DataUser> query = context.CreateQuery<DataUser>("Select value p from DataUsers as p");
                ObjectResult<DataUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (DataUser dataUser in results)
                {
                    context.DataUsers.DeleteObject(dataUser);
                }

                context.SaveChanges();

                return true;

            }
        }
        #endregion

        #region UTILITY USER RELATED METHODS
        /// <summary>
        /// Gets all the utility users.
        /// </summary>
        /// <returns>List of utility users.</returns>
        public static List<UtilityUser> GetAllUtilityUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<UtilityUser> query = context.CreateQuery<UtilityUser>("Select value p from UtilityUsers as p");
                ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Gets the Utility user by the login name.
        /// </summary>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>Utility user if found else will return null.</returns>
        public static UtilityUser GetUtilitiyUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetUtilitiyUserByLoginName(context, loginName);
            }
        }

        /// <summary>
        /// Gets the Utility user by the login name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>Utility user instance if found else will return null.</returns>
        public static UtilityUser GetUtilitiyUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<UtilityUser> query =
                    context.CreateQuery<UtilityUser>(
                    "Select value p from UtilityUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));

            ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (UtilityUser utilityUser in results) { return utilityUser; }

            return null;
        }

        /// <summary>
        /// Saves the utility user to application database.
        /// </summary>
        /// <param name="name">Utility user name.</param>
        /// <param name="login">Utility user login name.</param>
        /// <param name="password">Utility user password.</param>
        /// <returns>Saved utility user object.</returns>
        public static UtilityUser SaveUtilityUser(String name, String login, String password)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUser(context, new UtilityUser()
                {
                    ID = context.UtilityUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = true,
                });
            }
        }

        /// <summary>
        /// Saves the utility user to application database.
        /// </summary>
        /// <param name="name">Utility user name.</param>
        /// <param name="login">Utility user login name.</param>
        /// <param name="password">Utility user password.</param>
        /// <param name="active">Is Active.</param>
        /// <returns>Saved utility user object.</returns>
        public static UtilityUser SaveUtilityUser(String name, String login, String password, bool active)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUser(context, new UtilityUser()
                {
                    ID = context.UtilityUsers.NextId(f => f.ID),
                    Name = name,
                    Login = login,
                    Password = password,
                    Active = active,
                });
            }
        }

        /// <summary>
        /// Saves the utility user to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="utilityUser">Utility user to save.</param>
        /// <returns>Saved utility user object.</returns>
        public static UtilityUser SaveUtilityUser(ConfigDatabaseEntities context, UtilityUser utilityUser)
        {
            return context.UtilityUsers.AddAndSaveChanges(context, utilityUser);
        }

        /// <summary>
        /// Deletes the Utility user by the login name.
        /// </summary>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>True if utility user deleted successfully else false.</returns>
        public static bool DeleteUtilitiyUserByLoginName(String loginName)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteUtilitiyUserByLoginName(context, loginName))
                {
                    context.SaveChanges();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes the Utility user by the login name.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Utility user login name.</param>
        /// <returns>True if utility user deleted successfully else false.</returns>
        public static bool DeleteUtilitiyUserByLoginName(ConfigDatabaseEntities context, String loginName)
        {
            ObjectQuery<UtilityUser> query =
                    context.CreateQuery<UtilityUser>(
                    "Select value p from UtilityUsers as p Where p.Login = @Login"
                    , new ObjectParameter("Login", loginName));

            ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (UtilityUser utilityUser in results)
            {
                context.UtilityUsers.DeleteObject(utilityUser);

                return true;
            }

            return false;
        }

        /// <summary>
        /// Deletes all the utility users from application database.
        /// </summary>
        /// <returns>True if all utility user deleted successfully else false.</returns>
        public static bool DeleteAllUtilityUsers()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<UtilityUser> query = context.CreateQuery<UtilityUser>("Select value p from UtilityUsers as p");
                ObjectResult<UtilityUser> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (UtilityUser utilityUser in results)
                {
                    context.UtilityUsers.DeleteObject(utilityUser);
                }

                context.SaveChanges();

                return true;

            }
        }
        #endregion

        #region NOTIFICATION RELATED METHODS
        /// <summary>
        /// Gets the Notification by the notification id.
        /// </summary>
        /// <param name="notificationID">Notification id.</param>
        /// <returns>Notification if found else will return null.</returns>
        public static Notification GetNotificationByID(int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetNotificationByID(context, notificationID);
            }
        }

        /// <summary>
        /// Gets the Notification by the notification id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="notificationID">Notification id.</param>
        /// <returns>Notification if found else will return null.</returns>
        public static Notification GetNotificationByID(ConfigDatabaseEntities context, int notificationID)
        {
            ObjectQuery<Notification> query =
                    context.CreateQuery<Notification>(
                    "Select value p from Notifications as p Where p.NotificationID = @NotificationID"
                    , new ObjectParameter("NotificationID", notificationID));

            ObjectResult<Notification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (Notification notification in results) { return notification; }

            return null;
        }

        /// <summary>
        /// Saves the Notification to application database.
        /// </summary>
        /// <param name="notificationID">Notification ID.</param>
        /// <returns>Saved notification object.</returns>
        public static Notification SaveNotification(int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveNotification(context, new Notification()
                {
                    NotificationID = notificationID
                });
            }
        }

        /// <summary>
        /// Saves the notification to application database.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="notification">Notification to save.</param>
        /// <returns>Saved notification object.</returns>
        public static Notification SaveNotification(ConfigDatabaseEntities context, Notification notification)
        {
            return context.Notifications.AddAndSaveChanges(context, notification);
        }

        /// <summary>
        /// Deletes Notification by the notification id.
        /// </summary>        
        /// <param name="notificationID">Notification id.</param>
        /// <returns>True if notification deleted successfully else false.</returns>
        public static bool DeleteNotificationByID(int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteNotificationByID(context, notificationID))
                {
                    context.SaveChanges();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes Notification by the notification id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="notificationID">Notification id.</param>
        /// <returns>True if notification deleted successfully else false.</returns>
        public static bool DeleteNotificationByID(ConfigDatabaseEntities context, int notificationID)
        {
            ObjectQuery<Notification> query =
                    context.CreateQuery<Notification>(
                    "Select value p from Notifications as p Where p.NotificationID = @NotificationID"
                    , new ObjectParameter("NotificationID", notificationID));

            ObjectResult<Notification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (Notification notification in results)
            {
                context.Notifications.DeleteObject(notification);

                return true;
            }

            return false;
        }
        #endregion

        #region UTILITY USER ALLOWED NOTIFICATION RELATED METHODS
        /// <summary>
        /// Get Utility user allowed notifications.
        /// </summary>
        /// <returns>List of allowed notifications.</returns>
        public static List<UtilityUserAllowedNotification> GetAllUtilityUserNotifications()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<UtilityUserAllowedNotification> query
                    = context.CreateQuery<UtilityUserAllowedNotification>("Select value p from UtilityUserAllowedNotifications as p");
                ObjectResult<UtilityUserAllowedNotification> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Get Utility user allowed notifications by user Id.
        /// </summary>
        /// <param name="utilityUserID">Utility user Id.</param>
        /// <returns>List of allowed notifications.</returns>
        public static List<UtilityUserAllowedNotification> GetUtilityUserNotificationsByUtilityUserID(int utilityUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetUtilityUserNotificatiosnByUtilityUserID(context, utilityUserID);
            }
        }

        /// <summary>
        /// Get Utility user allowed notifications by user Id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="loginName">Utility user Id.</param>
        /// <returns>List of allowed notifications.</returns>
        public static List<UtilityUserAllowedNotification> GetUtilityUserNotificatiosnByUtilityUserID(ConfigDatabaseEntities context, int utilityUserID)
        {
            ObjectQuery<UtilityUserAllowedNotification> query =
                    context.CreateQuery<UtilityUserAllowedNotification>(
                    "Select value p from UtilityUserAllowedNotifications as p Where p.UtilityUserID = @UtilityUserID"
                    , new ObjectParameter("UtilityUserID", utilityUserID));

            ObjectResult<UtilityUserAllowedNotification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            return results.ToList();
        }

        /// <summary>
        /// Saves the allowd notifications ID for utility user to application database.
        /// </summary>
        /// <param name="utilityUserID">Utility user ID for which notification is to save.</param>
        /// <param name="notificationID">Notification ID.</param>
        /// <returns>Saved utility user allowed notification object.</returns>
        public static UtilityUserAllowedNotification SaveUtilityUserNotification(int utilityUserID, int notificationID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUserNotification(context, new UtilityUserAllowedNotification()
                {
                    ID = context.UtilityUserAllowedNotifications.NextId(f => f.ID),
                    UtilityUserID = utilityUserID,
                    NotificationID = notificationID,
                    Allowed = true,
                });
            }
        }

        /// <summary>
        /// Saves the allowd notifications ID for utility user to application database.
        /// </summary>
        /// <param name="utilityUserID">Utility user ID for which notification is to save.</param>
        /// <param name="notificationID">Notification ID.</param>
        /// <param name="allowed">True if sending the notification ID is allowed to send to utility user else false.</param>
        /// <returns>Saved utility user allowed notification object.</returns>
        public static UtilityUserAllowedNotification SaveUtilityUserNotification(int utilityUserID, int notificationID, bool allowed)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveUtilityUserNotification(context, new UtilityUserAllowedNotification()
                {
                    ID = context.UtilityUserAllowedNotifications.NextId(f => f.ID),
                    UtilityUserID = utilityUserID,
                    NotificationID = notificationID,
                    Allowed = allowed,
                });
            }
        }

        /// <summary>
        /// Saves the allowd notifications ID for utility user to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="utilityUserNotification">Utility user notification to save.</param>
        /// <returns>Saved utility user allowed notification object.</returns>
        public static UtilityUserAllowedNotification SaveUtilityUserNotification(ConfigDatabaseEntities context, UtilityUserAllowedNotification utilityUserNotification)
        {
            return context.UtilityUserAllowedNotifications.AddAndSaveChanges(context, utilityUserNotification);
        }

        /// <summary>
        /// Deletes the user's notification by the user Id.
        /// </summary>
        /// <param name="utilityUserID">Utility user Id.</param>
        /// <returns>True if user's notification deleted successfully else false.</returns>
        public static bool DeleteUtilityUserNotificationsByUtilityUserID(int utilityUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteUtilityUserNotificationsByUtilityUserID(context, utilityUserID))
                {
                    context.SaveChanges();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes the user's notification by the user Id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="utilityUserID">Utility user Id.</param>
        /// <returns>True if user's notification deleted successfully else false.</returns>
        public static bool DeleteUtilityUserNotificationsByUtilityUserID(ConfigDatabaseEntities context, int utilityUserID)
        {
            ObjectQuery<UtilityUserAllowedNotification> query =
                    context.CreateQuery<UtilityUserAllowedNotification>(
                    "Select value p from UtilityUserAllowedNotifications as p Where p.UtilityUserID = @UtilityUserID"
                    , new ObjectParameter("UtilityUserID", utilityUserID));

            ObjectResult<UtilityUserAllowedNotification> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (UtilityUserAllowedNotification utilityUserAllowedNotification in results)
            {
                context.UtilityUserAllowedNotifications.DeleteObject(utilityUserAllowedNotification);
            }

            return true;
        }
        #endregion

        #region SKELETON JOINT RELATED METHODS
        /// <summary>
        /// Gets the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="jointID">Joint id.</param>
        /// <returns>Skeleton Joint if found else will return null.</returns>
        public static SkeletonJoint GetSkeletonJointByID(int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetSkeletonJointByID(context, jointID);
            }
        }

        /// <summary>
        /// Gets the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="jointID">Joint id.</param>
        /// <returns>Skeleton Joint if found else will return null.</returns>
        public static SkeletonJoint GetSkeletonJointByID(ConfigDatabaseEntities context, int jointID)
        {
            ObjectQuery<SkeletonJoint> query =
                    context.CreateQuery<SkeletonJoint>(
                    "Select value p from SkeletonJoints as p Where p.JointID = @JointID"
                    , new ObjectParameter("JointID", jointID));

            ObjectResult<SkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (SkeletonJoint skeletonJoint in results) { return skeletonJoint; }

            return null;
        }

        /// <summary>
        /// Saves the Skeleton Joint to application database.
        /// </summary>
        /// <param name="jointID">Skeleton joint ID to save.</param>
        /// <returns>Saved skeleton joint object.</returns>
        public static SkeletonJoint SaveSkeletonJoint(int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveSkeletonJoint(context, new SkeletonJoint()
                {
                    JointID = jointID
                });
            }
        }

        /// <summary>
        /// Saves the Skeleton Joint to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="skeletonJoint">SkeletonJoint to save.</param>
        /// <returns>Saved skeleton joint object.</returns>
        public static SkeletonJoint SaveSkeletonJoint(ConfigDatabaseEntities context, SkeletonJoint skeletonJoint)
        {
            return context.SkeletonJoints.AddAndSaveChanges(context, skeletonJoint);
        }

        /// <summary>
        /// Deletes the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="jointID">Joint id to delete.</param>
        /// <returns>True if skeleton deleted successfully else false.</returns>
        public static bool DeleteSkeletonJointByID(int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteSkeletonJointByID(context, jointID))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Deletes the Skeleton Joint by the joint id.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="jointID">Joint id to delete.</param>
        /// <returns>True if skeleton deleted successfully else false.</returns>
        public static bool DeleteSkeletonJointByID(ConfigDatabaseEntities context, int jointID)
        {
            ObjectQuery<SkeletonJoint> query =
                    context.CreateQuery<SkeletonJoint>(
                    "Select value p from SkeletonJoints as p Where p.JointID = @JointID"
                    , new ObjectParameter("JointID", jointID));

            ObjectResult<SkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (SkeletonJoint skeletonJoint in results)
            {
                context.SkeletonJoints.DeleteObject(skeletonJoint);
                return true;
            }

            return false;
        }
        #endregion

        #region DATA USER ALLOWED SKELETON JOINTS DATA RELATED METHODS
        /// <summary>
        /// Gets the service client allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>List of registered skeleton joints against provided data user ID.</returns>
        public static List<DataUserAllowedSkeletonJoint> GetDataUserAllowedSkeletonJointsByDataUserID(int dataUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.GetDataUserAllowedSkeletonJointsByDataUserID(context, dataUserID);
            }
        }

        /// <summary>
        /// Gets the service client allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>List of registered skeleton joints against provided data user ID.</returns>
        public static List<DataUserAllowedSkeletonJoint> GetDataUserAllowedSkeletonJointsByDataUserID(ConfigDatabaseEntities context, int dataUserID)
        {
            ObjectQuery<DataUserAllowedSkeletonJoint> query =
                    context.CreateQuery<DataUserAllowedSkeletonJoint>(
                    "Select value p from DataUserAllowedSkeletonJoints as p Where p.DataUserID = @DataUserID"
                    , new ObjectParameter("DataUserID", dataUserID));

            ObjectResult<DataUserAllowedSkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            return results.ToList();
        }

        /// <summary>
        /// Saves the allowed skeleton joints ID for provided data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <param name="jointID">Joint ID.</param>        
        /// <returns>True if skeleton joint information added successfully else flase.</returns>
        public static DataUserAllowedSkeletonJoint SaveDataUserAllowedSkeletonJoint(int dataUserID, int jointID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUserAllowedSkeletonJoint(context, new DataUserAllowedSkeletonJoint()
                {
                    ID = context.DataUserAllowedSkeletonJoints.NextId(f => f.ID),
                    DataUserID = dataUserID,
                    JointID = jointID,
                    Allowed = true,
                });
            }
        }

        /// <summary>
        /// Saves the allowed skeleton joints ID for provided data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <param name="jointID">Joint ID.</param>
        /// <param name="allowed">True if data user can receive data of joint else flase.</param>
        /// <returns>True if skeleton joint information added successfully else flase.</returns>
        public static DataUserAllowedSkeletonJoint SaveDataUserAllowedSkeletonJoint(int dataUserID, int jointID, bool allowed)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SaveDataUserAllowedSkeletonJoint(context, new DataUserAllowedSkeletonJoint()
                {
                    ID = context.DataUserAllowedSkeletonJoints.NextId(f => f.ID),
                    DataUserID = dataUserID,
                    JointID = jointID,
                    Allowed = allowed,
                });
            }
        }

        /// <summary>
        /// Saves the data user's allowed skeleton joints information to application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUserAllowedSkeletonJoint">Data user allowed skeleton joints instance to save.</param>
        /// <returns>True if skeleton joint information added successfully else flase.</returns>
        public static DataUserAllowedSkeletonJoint SaveDataUserAllowedSkeletonJoint(ConfigDatabaseEntities context, DataUserAllowedSkeletonJoint dataUserAllowedSkeletonJoint)
        {
            return context.DataUserAllowedSkeletonJoints.AddAndSaveChanges(context, dataUserAllowedSkeletonJoint);
        }

        /// <summary>
        /// Delete data user allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>True if data user's allowed skeleton joints deleted successfully else false.</returns>
        public static bool DeleteDataUserAllowedSkeletonJointsByDataUserID(int dataUserID)
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                if (ConfigurationHelper.DeleteDataUserAllowedSkeletonJointsByDataUserID(context, dataUserID))
                {
                    context.SaveChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Delete data user allowed skeleton joints by data user ID.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="dataUserID">Data user ID.</param>
        /// <returns>True if data user's allowed skeleton joints deleted successfully else false.</returns>
        public static bool DeleteDataUserAllowedSkeletonJointsByDataUserID(ConfigDatabaseEntities context, int dataUserID)
        {
            ObjectQuery<DataUserAllowedSkeletonJoint> query =
                    context.CreateQuery<DataUserAllowedSkeletonJoint>(
                    "Select value p from DataUserAllowedSkeletonJoints as p Where p.DataUserID = @DataUserID"
                    , new ObjectParameter("DataUserID", dataUserID));

            ObjectResult<DataUserAllowedSkeletonJoint> results = query.Execute(ConfigurationHelper.executeMergeOption);

            foreach (DataUserAllowedSkeletonJoint dataUserAllowedSkeletonJoint in results)
            {
                context.DataUserAllowedSkeletonJoints.DeleteObject(dataUserAllowedSkeletonJoint);

            }

            return true;
        }
        #endregion

        #region SERVICE SETTINGS RELATED METHODS
        /// <summary>
        /// Gets service settings from application database
        /// </summary>
        /// <returns>List of service settings instances.</returns>
        public static List<ServiceSetting> GetServiceSettings()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<ServiceSetting> query
                    = context.CreateQuery<ServiceSetting>("Select value p from ServiceSettings as p");
                ObjectResult<ServiceSetting> results = query.Execute(ConfigurationHelper.executeMergeOption);

                return results.ToList();
            }
        }

        /// <summary>
        /// Saves service settings to application database.
        /// </summary>
        /// <param name="remotingServerPort">Remoting server port</param>
        /// <param name="remotingChannelName">Remoting channel name</param>
        /// <param name="webSocketServerIP">Web socket server ip</param>
        /// <param name="webSocketServerPort">Web socket server port</param>
        /// <param name="secureWebSocketServerIP">Secure web socket server ip</param>
        /// <param name="secureWebSocketServerPort">Secure web socket server port</param>
        /// <param name="runSecureSocketServer">Run secure web socket server</param>
        /// <param name="serverWebSocketCertificate">Web socket certificate path</param>
        /// <param name="logDirectory">Log directory</param>
        /// <param name="isLoggingEnabled">Logging enabled</param>
        /// <returns>Saved service setting object.</returns>
        public static ServiceSetting SaveServiceSettings(
            int remotingServerPort, String remotingChannelName, String webSocketServerIP, int webSocketServerPort, String secureWebSocketServerIP,
            int secureWebSocketServerPort, bool runSecureSocketServer, String serverWebSocketCertificate, String logDirectory, bool isLoggingEnabled)
        {
            DeleteServiceSettings();

            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                return ConfigurationHelper.SavServiceSettings(context, new ServiceSetting()
                {
                    RemotingServerPort = remotingServerPort,
                    RemotingChannelName = remotingChannelName,
                    WebSocketServerIP = webSocketServerIP,
                    WebSocketServerPort = webSocketServerPort,
                    SecureWebSocketServerIP = secureWebSocketServerIP,
                    SecureWebSocketServerPort = secureWebSocketServerPort,
                    RunSecureSocketServer = runSecureSocketServer,
                    ServerWebScoketCertificate = serverWebSocketCertificate,
                    LogDirectory = logDirectory,
                    IsLoggingEnabled = isLoggingEnabled,
                    ID = context.ServiceSettings.NextId(f => f.ID),
                });
            }
        }

        /// <summary>
        /// Saves the service settings in the application database.
        /// </summary>
        /// <param name="context">Database context instance.</param>
        /// <param name="serviceSettings">Service settings to be saved.</param>
        /// <returns>Saved service setting object.</returns>
        public static ServiceSetting SavServiceSettings(ConfigDatabaseEntities context, ServiceSetting serviceSettings)
        {
            return context.ServiceSettings.AddAndSaveChanges(context, serviceSettings);
        }

        /// <summary>
        /// Deletes service settings
        /// </summary>
        /// <returns>True if service settings deleted successfully else false.</returns>
        private static bool DeleteServiceSettings()
        {
            using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
            {
                ObjectQuery<ServiceSetting> query = context.CreateQuery<ServiceSetting>("Select value p from ServiceSettings as p");
                ObjectResult<ServiceSetting> results = query.Execute(ConfigurationHelper.executeMergeOption);

                foreach (ServiceSetting serviceSettings in results)
                {
                    context.ServiceSettings.DeleteObject(serviceSettings);
                }

                context.SaveChanges();

                return true;

            }
        }
        #endregion

        #endregion
    }
}